<?php

namespace app\adminapi\service;

use app\adminapi\dto\sysuser\LoginRepVO;
use app\adminapi\dto\sysuser\LoginReqVO;
use app\adminapi\dto\sysuser\ModifyAavtarReqVO;
use app\adminapi\dto\sysuser\ModifyPwdReqVO;
use app\adminapi\model\sysuser\SysUserDO;
use app\adminapi\model\sysuser\SysUserRoleDO;
use app\common\cache\AdminTokenCache;
use app\common\exception\OtherException;
use app\common\utils\AddressUtils;
use app\common\utils\IpUtils;
use app\common\utils\JWTUtils;
use app\common\utils\PasswordUtil;
use Jenssegers\Agent\Agent;

class SysUserService
{
    public function login(LoginReqVO $reqVO): LoginRepVO
    {
        $validResult = $this->loginBeforeCheck($reqVO);
        $token = JWTUtils::generateToken($validResult->userId);
        (new AdminTokenCache())->setAdminToken($token, $validResult->userId);
        return (new LoginRepVO())
            ->setToken($token)
            ->setAccount($validResult->userName)
            ->setAvatar($validResult->avatar);
    }

    public function modifyPwd(ModifyPwdReqVO $modifyPwdReqVO)
    {
        $userId = request()->adminId;
        $this->validateSysUserExists($userId);
        $exist = (new SysUserDO())->where('user_id', $userId)
            ->find();
        // 校验密码
        if (!PasswordUtil::match($modifyPwdReqVO->getOldPassword(), $exist->password)) {
            throw new OtherException('旧密码错误');
        } else {
            return SysUserDO::where('user_id', $userId)->update(['password' => $modifyPwdReqVO->getNewPassword()]);
        }
    }

    public function getSysUser(int $userId)
    {
        $this->validateSysUserExists($userId);
        $userInfo = (new SysUserDO())->where('user_id', $userId)->find();
        if ($userInfo->isRoot != 1) {
            $sysUserRole = (new SysUserRoleService())->getSysUserRole($userId);
            $sysRole = (new SysRoleService())->getSysRole($sysUserRole->roleId);
            $userInfo['roleId'] = $sysUserRole->roleId;
            $userInfo['roleName'] = $sysRole->roleName;
        }
        return $userInfo;
    }

    public function modifyAvatar(ModifyAavtarReqVO $modifyAavtarReqVO)
    {
        $userId = request()->adminId;
        $this->validateSysUserExists($userId);
        return SysUserDO::where('user_id', $userId)->update(['avatar' => $modifyAavtarReqVO->getAvatar()]);
    }

    public function list(array $param)
    {
        $where = [];
        if (isset($param['userName'])) {
            $where[] = ['user_name', 'like', '%' . $param['userName'] . '%'];
        }
        if (isset($param['phonenumber'])) {
            $where[] = ['phonenumber', '=', $param['phonenumber']];
        }
        if (isset($param['status'])) {
            $where[] = ['status', '=', $param['status']];
        }
        if (isset($param['timeArr'])) {
            $where[] = ['create_time', 'between', $param['timeArr']];
        }
        $paginate['list_rows'] = $param['pageSize'];
        if (isset($param['pageNo'])) {
            $paginate['page'] = $param['pageNo'];
        }
        $result = (new SysUserDO())
            ->where($where)
            ->paginate($paginate)
            ->toArray();
        return [
            'total' => $result['total'],
            'list' => $result['data']
        ];
    }

    public function addSysUser(array $sysUserDO)
    {
        $this->validateUserNameExists($sysUserDO['userName'], null);
        $model = new SysUserDO();
        $model->startTrans();
        try {
            $model->save($sysUserDO);
            SysUserRoleDO::create(['user_id' => $model->userId, 'role_id' => $sysUserDO['roleId']]);
            $model->commit();
            return 1;
        } catch (\Exception $e) {
            $model->rollback();
            throw new OtherException($e->getMessage());
        }
    }

    public function deleteSysUser(int $userIds)
    {
        $this->validateSysUserExists($userIds);
        $model = SysUserDO::find($userIds);
        $model->startTrans();
        try {
            (new SysUserRoleService())->deleteUserRoleByUserId($userIds);
            $model->delete();
            $model->commit();
            return 1;
        } catch (\Exception $e) {
            $model->rollback();
            throw new OtherException($e->getMessage());
        }
    }

    public function updateSysUser(array $sysUserDO)
    {
        $this->validateSysUserExists($sysUserDO['userId']);
        $this->validateUserNameExists($sysUserDO['userName'], $sysUserDO);
        $model = SysUserDO::find($sysUserDO['userId']);
        $model->startTrans();
        try {
            if ($sysUserDO['roleId']) {
                (new SysUserRoleService())->addSysUserRole(['userId' => $sysUserDO['userId'], 'roleId' => $sysUserDO['roleId']]);
            }
            $model->save($sysUserDO);
            $model->commit();
            return 1;
        } catch (\Exception $e) {
            $model->rollback();
            throw new OtherException($e->getMessage());
        }
    }

    public function changeSysUserStatus(array $sysUserDO)
    {
        $this->validateSysUserExists($sysUserDO['userId']);
        return SysUserDO::update($sysUserDO);
    }

    public function resetPwd(array $sysUserDO)
    {
        $this->validateSysUserExists($sysUserDO['userId']);
        return SysUserDO::update($sysUserDO);
    }

    // 登录前校验
    private function loginBeforeCheck(LoginReqVO $loginReqVO): SysUserDO
    {
        $loginLogParam = [
            'user_name' => $loginReqVO->getUserName(),
            'ip_addr' => IpUtils::getIpAddr(),
            'login_location' => AddressUtils::getRealAddressByIP(IpUtils::getIpAddr()),
            'browser' => (new Agent())->browser(),
            'os' => (new Agent())->platform(),
            'login_time' => time()
        ];
        $validExist = (new SysUserDO())
            ->where('user_name', $loginReqVO->getUserName())
            ->find();
        if (is_null($validExist)) {
            $loginLogParam['status'] = 1;
            $loginLogParam['msg'] = '用户名或密码错误';
            (new SysLoginLogService())->addSysLoginLog($loginLogParam);
            throw new OtherException('用户名或密码错误');
        } else {
            if ($validExist->status == 1) {
                $loginLogParam['status'] = 1;
                $loginLogParam['msg'] = '用户已被禁用';
                (new SysLoginLogService())->addSysLoginLog($loginLogParam);
                throw new OtherException('用户已被禁用');
            } else {
                if (!PasswordUtil::match($loginReqVO->getPassword(), $validExist->password)) {
                    $loginLogParam['status'] = 1;
                    $loginLogParam['msg'] = '用户名或密码错误';
                    (new SysLoginLogService())->addSysLoginLog($loginLogParam);
                    throw new OtherException('用户名或密码错误');
                } else {
                    $loginLogParam['status'] = 0;
                    $loginLogParam['msg'] = '登录成功';
                    (new SysLoginLogService())->addSysLoginLog($loginLogParam);
                    return $validExist;
                }
            }
        }
    }

    private function validateSysUserExists(int $userId)
    {
        if (empty((new SysUserDO())->where('user_id', $userId)->find())) {
            throw new OtherException('用户不存在');
        }
    }

    private function validateUserNameExists(string $userName, $oldInfo)
    {
        $where[] = ['user_name', '=', $userName];
        if ($oldInfo !== null) {
            $where[] = ['user_id', '<>', $oldInfo['userId']];
        }
        $exist = (new SysUserDO())->where($where)->find();
        if ($exist) {
            throw new OtherException('用户名已存在');
        }
    }
}